package com.gitee.wsl.lang.bytearray


interface Sliceable {
     operator fun get(range: IntRange): ByteSlice

     fun fullSlice(): ByteSlice
}

 data class ByteSlice( val bytes: ByteArray,  val start: Int,  val length: Int) : Iterable<Byte> {
    init {
        require(start >= 0 && start + length <= bytes.size) { "Slice must be within range of the array (0..${bytes.size})!" }
    }

    override fun iterator(): Iterator<Byte> {
        return SliceIterator(this)
    }

     operator fun set(index: Int, value: Byte) {
        bytes[start + index] = value
    }

     operator fun get(index: Int): Byte {
        return bytes[start + index]
    }

     fun copyInto(slice: ByteSlice) {
        bytes.copyInto(slice.bytes, slice.start, start, start + length)
    }

     fun contentEquals(other: ByteSlice): Boolean {
        if (length != other.length) return false

        for (i in 0 until length) if (this[i] != other[i]) return false

        return true
    }

     companion object {
         val Empty: ByteSlice = ByteSlice(ByteArray(0), 0, 0)
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other == null || this::class != other::class) return false

        other as ByteSlice

        if (start != other.start) return false
        if (length != other.length) return false
        if (!bytes.contentEquals(other.bytes)) return false

        return true
    }

    override fun hashCode(): Int {
        var result = start
        result = 31 * result + length
        result = 31 * result + bytes.contentHashCode()
        return result
    }
}

 class SliceIterator( val slice: ByteSlice) : Iterator<Byte> {
    private var pos = 0

    override fun hasNext(): Boolean {
        return pos < slice.length
    }

    override fun next(): Byte {
        return slice[pos++]
    }
}

 operator fun ByteArray.get(range: IntRange): ByteSlice {
    if (range.first < 0 || range.last > size) throw IndexOutOfBoundsException("Range $range is out of bounds for length $size")

    return ByteSlice(this, range.first, range.last - range.first)
}

 fun ByteArray.fullSlice(): ByteSlice {
    return this[0..size]
}